#include "menu_port.h"
#include "platform.h"
#include "usbd_cdc_if.h"


static uint8_t Menu_Buf[Max_InputBuf_Size] = {0};

//  菜单 日志复用， 只有菜单定义为 1
#ifdef LOGGER_MENU_MISC_HW
extern int MenuPort_Get_Status(  );
// osSemaphoreId_t menu_logger_miscHandle;
// const osSemaphoreAttr_t menu_logger_misc_attributes = {
//     .name = "menu_logger_misc"};
#endif


extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern const struct menu_tree_node menu_tree[];
// extern osMessageQueueId_t menuMsgQueueHandle;
// extern osSemaphoreId_t elog_menuHandle;

#define  MenuPort_OBJ   &huart1


//  接受到菜单输入
osSemaphoreId_t menu_inputHandle;
const osSemaphoreAttr_t menu_input_attributes = {
    .name = "menu_input"};

osThreadId_t menu_taskHandle;
const osThreadAttr_t menu_task_attributes = {
    .name = "menu_task",
    .stack_size = 256 * 4,
    .priority = (osPriority_t) osPriorityLow,
};

void menu_task(void *argument);


MenuPort_TypeDef my_menu_port = {
    NULL,0,0,0
    ,NULL 
    ,MenuPort_Output,MenuPort_Input
    ,MenuPort_Output_Cplt,MenuPort_Input_Callback
    ,MenuPort_Save,MenuPort_Get
    ,MenuPort_Get_Status,MenuPort_Set_Status
    ,Menu_Buf,0
};


int * MenuPort_Init(  )
{
    // Handle->output =   MenuPort_Output;
    // Handle->input =   MenuPort_Input;
    // Handle->output_cplt =   MenuPort_Output_Cplt;
    // Handle->input_callback =   MenuPort_Input_Callback;
    // Handle->save =   MenuPort_Save;
    // Handle->get =   MenuPort_Get;
    // Handle->get_status =   MenuPort_Get_Status;
    // Handle->set_status =   MenuPort_Set_Status;
    // (Viper_TypeDef *)malloc(sizeof(Viper_TypeDef));
    struct menu *handle = (struct menu *)malloc(sizeof(struct menu));
    my_menu_port.menu = handle;
    menu_init(my_menu_port.menu, menu_tree, (void*)MenuPort_OBJ, (menu_output_function_type)my_menu_port.output );
 
    my_menu_port.obj_class =   NULL;
    my_menu_port.menu->output =   my_menu_port.output;
    my_menu_port.menu->check_passwd =   NULL;

    return 0;
}


int MenuPort_Get_Status(  )
{
    return my_menu_port.is_working;
}

void MenuPort_Set_Status( uint8_t status )
{
    my_menu_port.is_working = status;
}

int MenuPort_Output( uint8_t * buf, uint32_t size){

    //  HAL_UART_Transmit_IT(menuport->huart, buf, size);
    //  HAL_UART_Transmit_DMA(menuport->huart, buf, size);
    HAL_UART_Transmit(MenuPort_OBJ, buf, size,0xFFFF);
	return 0;

}

int MenuPort_Output_Cplt() {
	return 0;
}

void MenuPort_Input() {
    my_menu_port.rcv_size =0;
    memset( (void*)my_menu_port.rcv_buf, 0,Max_InputBuf_Size);
    // HAL_UARTEx_ReceiveToIdle_DMA(MenuPort_OBJ,Menu_Buf,sizeof(Menu_Buf));
    __HAL_UART_ENABLE_IT(MenuPort_OBJ, UART_IT_IDLE);
    HAL_UART_Receive_DMA(MenuPort_OBJ,my_menu_port.rcv_buf,Max_InputBuf_Size);
}

int MenuPort_Input_Callback(uint8_t *buf, uint32_t size)
{
    osSemaphoreRelease(menu_inputHandle);
    my_menu_port.rcv_size =size;
    // menu_parse_callback(&menu,(char *)buf, size);
}

int MenuPort_Save( ){

    int ret = 0;
    // ret = HAL_UART_Receive(objclass,buf,size,0xFFFF);
    return ret;
}


int MenuPort_Get(   ){

    int ret = 0;
    return ret;
}

int MenuPort_Check_PassWord(struct menu *menu, char *passwd, uint32_t size){

    char  pass[] = "eseaoptics";
    if (sizeof(pass)!=size) return -1;
    for (size_t i = 0; i < size; i++)
    {
        return (pass[i]!=passwd[i])?-1:0; 
    }
}


void menu_task( void *argument){
    // static uint8_t  recv_buff[Max_InputBuf_Size] ={0};
    MenuPort_Init( );
    osSemaphoreAcquire(menu_inputHandle,osWaitForever);
    // menu_init(my_menu_port.menu, menu_tree, (void*)MenuPort_OBJ, (menu_output_function_type)my_menu_port.output );

    // // 开启菜单接收
    // my_menu_port.input();
    uint8_t *state = argument;

    for ( ; ; )
    {
        switch (*state)
        {
        case MENU_PORT_STATE_WAIT:
            osDelay(10);
            break;
        case MENU_PORT_STATE_START:   //< begin to receive data
            printf(" MENU_PORT_STATE_START ... \r\n");
            // MenuPort_Input();
            my_menu_port.input();

            *state = MENU_PORT_STATE_INPUT;
            break;
        case MENU_PORT_STATE_INPUT:  //  wait for input
            printf(" MENU_PORT_STATE_INPUT   wait ... \r\n");
            if ( osSemaphoreAcquire(menu_inputHandle,0x0F) == osOK )
            {
                my_menu_port.set_status(1);
                // 将buf 处理成带执行的菜单命令
                menu_parse_callback(my_menu_port.menu, (char*)my_menu_port.rcv_buf, my_menu_port.rcv_size);
                *state = MENU_PORT_STATE_OUTPUT;
                break;
            } 
            my_menu_port.idle++;
            if  ( my_menu_port.idle > 4000*5 ) 
            {
                *state = MENU_PORT_STATE_IDLE;
            }
            continue;  
        case MENU_PORT_STATE_OUTPUT:  //  output
            printf(" MENU_PORT_STATE  output ... flag_ready %d  -- menu->input_con  %d\r\n"
                    , my_menu_port.menu->flag_ready,my_menu_port.menu->input_con);
            my_menu_port.idle = 0;
            my_menu_port.set_status(1);

            // menu display , print,  callback repeatedly
            menu_print_callback(my_menu_port.menu);
            if (my_menu_port.menu -> flag_ready == 2)
            {
                *state = MENU_PORT_STATE_START;
            }
            break;     
 
        case MENU_PORT_STATE_IDLE:  //  IDLE
            my_menu_port.idle = 0;
            my_menu_port.set_status(0);
            menu_exit(my_menu_port.menu);
            *state = MENU_PORT_STATE_STOP;
            break;  
        case MENU_PORT_STATE_SAVE:  //  SAVE
            my_menu_port.save( );
            *state = MENU_PORT_STATE_STOP;
            break;  
        case MENU_PORT_STATE_STOP:  //  stop to start
            *state = MENU_PORT_STATE_START;
            break;  
        default:
            break;
        }
        osDelay(10);
        // //   处理接收到的消息, 消息队列？  -- 由中断处理回调
        // if ( osSemaphoreAcquire(menu_inputHandle,0xFF) == osOK )
        // {
        //     my_menu_port.idle = 0;
        //     my_menu_port.set_status(1);
        //     // 将buf 处理成带执行的菜单命令
        //     menu_parse_callback(&menu, (char*)Menu_Buf, sizeof(Menu_Buf));
        //     // 处理菜单输出 显示  打印
        //     menu_print_callback(&menu);
        //     continue;
        // }

        // // menu idle， exit automatically
        // if( my_menu_port.get_status() == 1 )
        // {
        //     my_menu_port.idle++;
        //     osDelay(10);
        //     if  ( my_menu_port.idle < 6000*5 ) continue;
        // }

        // // 菜单退出
        // my_menu_port.idle = 0;
        // my_menu_port.set_status(0);

        // menu_exit(my_menu_port.menu);

        // //  处理数据保存
        // my_menu_port.save( );
    }
}


void menu_port( void *argument){

// #ifdef MENU_LOGGER_MISC_HW
//     menu_logger_miscHandle = osSemaphoreNew(1, 1, &menu_logger_misc_attributes);
//     osSemaphoreRelease(menu_logger_miscHandle);
// #endif

    menu_inputHandle = osSemaphoreNew(1, 1, &menu_input_attributes);
    osSemaphoreRelease(menu_inputHandle);

    menu_taskHandle = osThreadNew( menu_task, &my_menu_port.state, &menu_task_attributes);

}


















// void isr_menu_rcv_callback(uint8_t *buf, uint32_t size)
// {
//     osSemaphoreRelease(menu_inputHandle);
//     // menu_parse_callback(&menu,(char *)buf, size);
// }


// void menu_logger_switch(uint8_t sel)
// {
//     menu_logger_sel = sel;
// }

// int __menu_send(void *objclass,char *buf,uint32_t size)
// {
//     int ret;
//     ret = HAL_UART_Transmit(objclass,buf,size,0xFFFF);
//     return ret;
// }

// int __menu_rcv(void *objclass,char *buf,uint32_t size)
// {
//     int ret;
//     ret = HAL_UARTEx_ReceiveToIdle_DMA(objclass,buf,size);
//     return ret;
// }

// int __menu_save(void )
// {
//     int ret = 0;
//     // ret = HAL_UART_Receive(objclass,buf,size,0xFFFF);
//     return ret;
// }










// void MenuPort_Setup( MenuPort_t *menuport, UART_HandleTypeDef *huart, GPIO_TypeDef *gpio, uint16_t pin, uint8_t mode ,uint8_t trans_mode)
// {
// 	menuport->huart = huart;
// 	menuport->gpio  = gpio;
// 	menuport->pin  = pin;
// 	menuport->mode  = mode;
// 	menuport->trans_mode  = trans_mode;
 
// }

// /* 待传入的函数 实际函数*/
// int MenuPort_Send(MenuPort_t *menuport,  uint8_t * buf, uint32_t size){
// 	if( menuport->mode ==1 ) {
// 		HAL_GPIO_WritePin(menuport->gpio,menuport->pin ,  SET);
// 	}

// 	switch (menuport->trans_mode)
// 	{
// 		case 1:
// 			HAL_UART_Transmit_IT(menuport->huart, buf, size);
// 			break;
// 		case 2:
// 			HAL_UART_Transmit_DMA(menuport->huart, buf, size);
// 			break;	
// 		default:
// 			HAL_UART_Transmit(menuport->huart, buf, size,0xFFFF);
// 	}

// 	if( menuport->mode ==1 ) {
// 		HAL_GPIO_WritePin( menuport->gpio, menuport->pin ,  RESET );
// 	}
// 	return 0;

// }

// void Menuport_receive_callback(MenuPort_t *menuport, uint8_t *buf,uint32_t size)
// {
// 	/* 接收回调 中断直接调用menu， 不经过menuport回调*/
// 	menu_parse_callback( menuport->menu, (char *)buf,  size );
// }

// void menuport_exit( MenuPort_t *menuport)
// {
//     if ( menu_get_state(menuport->menu) != 0 )
//     {
// 		osSemaphoreRelease(elog_menuHandle);   /* 一直持有到菜单结束才释放*/
// 		menu_exit(menuport->menu );
// 	}  
// }

// void Menuport_Error(char *error)
// {
//     /*  定制输出 error内容*/
//     // printf (error);
//     while (1);
// }

// // menu 两个任务 menu_entry  menu_task 是否可以一个任务去搞
// //  menu_entry 等待消息队列，执行  menu_parse_callback
// //  menu_task 执行  menu_print_callback  -->  display
// void menu_entry( void *argument)
// {
//     osStatus_t status;
//     uint8_t  recv_buff[Max_InputBuf_Size] ={0};
//     menuport = MenuPort_Init();
//     MenuPort_Setup( menuport, MenuUart, NULL, 0, 0, 0 );   /* poll 模式发送，DMA IT 模式会出问题*/
//     menu_init(menuport->menu, menu_tree, (void*)menuport, ( menu_send_function_type ) MenuPort_Send );
//     for ( ; ; )
//     {
//         osDelay(10);
//         status = osMessageQueueGet( menuMsgQueueHandle,   (void *)recv_buff, NULL, 0xFF );
//         if (status ==osOK)
//         { 
//             /*菜单任务  拷贝值到当前菜单，执行菜单任务*/
//             if ( menu_get_state(menuport->menu) == 0)
//             {  osSemaphoreAcquire( elog_menuHandle, 0xFF ) ;   /* 一直持有到菜单结束才释放*/
//               // Is_Menu_Running = 1; 
//             }

//             menu_parse_callback(menuport->menu, (char*)Menu_Buf, sizeof(Menu_Buf));

//             __HAL_UART_CLEAR_IDLEFLAG(menuport->huart);
//             HAL_UARTEx_ReceiveToIdle_DMA( menuport->huart, Menu_Buf, 256 ); 
//             // menu_print_callback(&menu);
//             // menu_parse_callback(&menu,)
//             // printf("alreay get info...  \r\n"); /** 打印卡死 原因？ */
//         } 
//     }
// }